IFIX, Correlação e Previsão

Clique abaixo para selecionar qual deseja visualizar.

Resumo

Este estudo buscou analisar o comportamento do IFIX. Para tal, foram coletados dados históricos de janeiro de 2015 à setembro de 2023. Adicionalmente, foi explorado correlação com os índices IBOV, Selic e IPCA. Posteriormente, utilizou-se o modelo estatístico ARIMA que combina elementos de autocorrelação (AR) e médias móveis (MA) para capturar padrões temporais nos dados. Concluiu-se que um período maior e intervalos menores, forneceria robustez a estudos futuros. Evidencia-se esta afirmativa em virtude do contexto vivido no período em questão, múltiplos governos, impeachment, pandemia, amplitude da taxa Selic, crises… Ainda assim, o modelo ARIMA identificou tendências e padrões de predição, passível de se observar ao analisar experimento “out-of-sample”. Ademais, independentemente, o presente trabalho cumpriu com êxito seus objetivos. Orientado sob viés didático, exploratório, especulativo e a fim de demonstrar repertório do autor acerca dos temas em questão.

Introdução

Assume-se que um bom investimento é realizado no lugar, momento e valor adequado. Propôs-se aqui debruçar-se sobre o comportamento do IFIX (Índice de Fundos de Investimentos Imobiliários) com caráter exploratório a fim de analisar a intrínseca relação desse índice.

Para tal, analisou-se correlação com outros índices. Em particular IBOV (ou IBOVESPA - Índice da Bolsa de Valores de São Paulo), Selic (Sistema Especial de Liquidação e Custódia) e IPCA (Índice Nacional de Preços ao Consumidor Amplo). O período analisado foi de janeiro de 2015 à setembro de 2023, com intervalo mensal.

Em um segundo momento utilizou-se o modelo estatístico ARIMA que combina elementos de autocorrelação (AR) e médias móveis (MA) para capturar padrões temporais nos dados.

Objetivos

Possui como objetivos gerais:

  • Demonstrar repertório do autor acerca dos conteúdos aqui abordados.
  • Analisar comportamento do IFIX ao longo do período proposto.

Possui como objetivos específicos:

  • Analisar correlação do IFIX com outros índices.
  • Explorar capacidade de predição utilizando modelo ARIMA.

Metodologia

O banco de dados foi formado com suas fontes, os índices Selic e IPCA cedidos pelo BACEN (Banco Central do Brasil) e os índices IFIX e IPCA foram coletados pela biblioteca TvDataFeed que possui como fonte o site da TradingView. Mais detalhes sobre a metodologia podem ser obtidos no tópico Replicabilidade e ao longo do próprio trabalho.

“O presente material (…) não se trata de recomendação de compra ou venda de ativos e produtos financeiros. Qualquer decisão de investimento deve ser realizada por meio de aconselhamento profissional e personalizado, levando em consideração os objetivos, necessidades e situação financeira específica de cada investidor.”

(Orientação sobre divulgação de informações sobre investimentos. Comissão de Valores Mobiliários - CVM)

Ferramentas

Para exibir as bibliotecas e ferramentas utilizadas clique no botão:

Bibliotecas R:

library(tidyverse)
library(plotly)
library(lubridate)
library(tibble)
library(jsonlite)
library(httr)
library(reticulate)
library(dplyr)
library(tseries)
library(forecast)

Bibliotecas Python:

from tvDatafeed import TvDatafeed, Interval
import pandas as pd

Tenha, como exemplo, a linha de código httr::GET(url). Embora seja desnecessária a referência httr:: ela foi explicitada ao longo do presente trabalho por motivos pessoais e de boas práticas, como organização e referenciação da origem da função utilizada.

Replicabilidade

Neste tópico foram detalhadas as versões para possibilitar replicação dos resultados obtidos. Para mais detalhes, clique no botão:

Caso queira replicar, certifique-se de ter os pacotes necessários rodando o seguinte código:

library <- c("tidyverse",
             "plotly",
             "lubridate",
             "tibble",
             "jsonlite",
             "httr",
             "reticulate",
             "dplyr",
             "tseries",
             "forecast")

if (sum(as.numeric(!library %in% installed.packages())) != 0) {
  instalador <- library[!library %in% installed.packages()]
  for (i in 1:length(instalador)) {
    install.packages(instalador, dependencies = T)
    break()}
  sapply(library, require, character = T) 
} else {
  sapply(library, require, character = T) 
}
##  tidyverse     plotly  lubridate     tibble   jsonlite       httr reticulate 
##       TRUE       TRUE       TRUE       TRUE       TRUE       TRUE       TRUE 
##      dplyr    tseries   forecast 
##       TRUE       TRUE       TRUE

Foi também utilizado a versão forked do TvDataFeed, para instalar:

!pip install --upgrade --no-cache-dir git+https://github.com/rongardF/tvdatafeed.git

A versão do R, Python e Reticulate.

rrtver <- toString(packageVersion("reticulate"))
rver <- R.version.string
pver = (__import__('sys').version)[0:6]
print(" Reticulate version", r.rrtver,"\n Python version", pver,"\n", r.rver)
##  Reticulate version 1.32.0 
##  Python version 3.9.16 
##  R version 4.3.1 (2023-06-16)

Os pacotes e versões utilizadas foram:

pckgver <- for (package_name in sort(loadedNamespaces())) {print(paste(package_name, packageVersion(package_name)))}
## [1] "base 4.3.1"
## [1] "bslib 0.5.0"
## [1] "cachem 1.0.8"
## [1] "cli 3.6.1"
## [1] "colorspace 2.1.0"
## [1] "compiler 4.3.1"
## [1] "curl 5.0.0"
## [1] "data.table 1.14.8"
## [1] "datasets 4.3.1"
## [1] "digest 0.6.33"
## [1] "dplyr 1.1.3"
## [1] "evaluate 0.21"
## [1] "fansi 1.0.4"
## [1] "fastmap 1.1.1"
## [1] "forcats 1.0.0"
## [1] "forecast 8.21.1"
## [1] "fracdiff 1.5.2"
## [1] "generics 0.1.3"
## [1] "ggplot2 3.4.2"
## [1] "glue 1.6.2"
## [1] "graphics 4.3.1"
## [1] "grDevices 4.3.1"
## [1] "grid 4.3.1"
## [1] "gtable 0.3.3"
## [1] "here 1.0.1"
## [1] "hms 1.1.3"
## [1] "htmltools 0.5.6"
## [1] "htmlwidgets 1.6.2"
## [1] "httr 1.4.6"
## [1] "jquerylib 0.1.4"
## [1] "jsonlite 1.8.7"
## [1] "knitr 1.43"
## [1] "lattice 0.21.8"
## [1] "lazyeval 0.2.2"
## [1] "lifecycle 1.0.3"
## [1] "lmtest 0.9.40"
## [1] "lubridate 1.9.2"
## [1] "magrittr 2.0.3"
## [1] "Matrix 1.6.0"
## [1] "methods 4.3.1"
## [1] "munsell 0.5.0"
## [1] "nlme 3.1.162"
## [1] "nnet 7.3.19"
## [1] "parallel 4.3.1"
## [1] "pillar 1.9.0"
## [1] "pkgconfig 2.0.3"
## [1] "plotly 4.10.2"
## [1] "png 0.1.8"
## [1] "purrr 1.0.2"
## [1] "quadprog 1.5.8"
## [1] "quantmod 0.4.25"
## [1] "R6 2.5.1"
## [1] "Rcpp 1.0.11"
## [1] "readr 2.1.4"
## [1] "reticulate 1.32.0"
## [1] "rlang 1.1.1"
## [1] "rmarkdown 2.23"
## [1] "rprojroot 2.0.3"
## [1] "rstudioapi 0.14"
## [1] "sass 0.4.7"
## [1] "scales 1.2.1"
## [1] "stats 4.3.1"
## [1] "stringi 1.7.12"
## [1] "stringr 1.5.0"
## [1] "tibble 3.2.1"
## [1] "tidyr 1.3.0"
## [1] "tidyselect 1.2.0"
## [1] "tidyverse 2.0.0"
## [1] "timechange 0.2.0"
## [1] "timeDate 4022.108"
## [1] "tools 4.3.1"
## [1] "tseries 0.10.54"
## [1] "TTR 0.24.3"
## [1] "tzdb 0.4.0"
## [1] "urca 1.3.3"
## [1] "utf8 1.2.3"
## [1] "utils 4.3.1"
## [1] "vctrs 0.6.3"
## [1] "viridisLite 0.4.2"
## [1] "withr 2.5.0"
## [1] "xfun 0.40"
## [1] "xts 0.13.1"
## [1] "yaml 2.3.7"
## [1] "zoo 1.8.12"

Por fim, fixando a seed para valor fixos/replicáveis em eventual geração aleatória.

set.seed(0)

Banco de dados

Para exibir detalhes sobre a aquisição dos Data Frames clique no botão:

Definição inicial dos parâmetros:

Caso seja necessário, importe credenciais de um arquivo *.json para o ambiente Python.

# Definição do Usuário/Senha (Para aquisição do IBOV e IFIX).
#tradingview <- jsonlite::fromJSON("tradingview.json")
#py$username <- tradingview$username
#py$password <- tradingview$password

A biblioteca TvDataFeed permite realizar consultas sem estar logado, contudo terá limitação em determinadas requisições. Embora neste trabalho não tenha sido necessário Login, foi disponibilizado, no código acima, a possibilidade de realizar login apartir de um arquivo json contendo usuário e senha.

Índices IFIX e IBOV

As principais bibliotecas (como quantmod,tidyquant,BatchGetSymbols, investpy, …) “puxam” dados do Yahoo Finance, que são incompletos para o índice do IFIX. Também, algumas dessas bibliotecas foram descontinuadas como é o caso do Google Finance em março de 2018, e o site Investing. Alpha Vantage também não é uma opção viável. Com isto em mente, a seguir foi utilizada a biblioteca fork do TvDataFeed que recebe dados do site TradingView. Nesta parte será utilizado Python, e posteriormente retornado para R.

# Abaixo exemplo caso necessite de Login:
# tv = TvDatafeed(username, password)
tv = TvDatafeed()
## you are using nologin method, data you access may be limited

Para este estudo em particular não é necessário login como citado anteriormente.

# São 107 'n_bars' por ser a quantidade de meses para que inicie em 12/2014.
ifix = tv.get_hist(symbol='IFIX',exchange='BMFBOVESPA',interval=Interval.in_monthly,n_bars=106)
ibov = tv.get_hist(symbol='IBOV',exchange='BMFBOVESPA',interval=Interval.in_monthly,n_bars=106)
IFIX

Recebendo e exibindo o Data Frame do IFIX no ambiente R:

ifix_df <- py$ifix
ifix_df
IBOV

Recebendo e exibindo o Data Frame do IBOV no ambiente R:

ibov_df <- py$ibov
ibov_df

Índices IPCA e Selic

Os índices a seguir foram adquiridos por meio de requisição pela API do BACEN (Banco Central do Brasil):

https://api.bcb.gov.br/dados/serie/bcdata.sgs.{codigo_serie}/dados?formato=json&dataInicial={dataInicial}&dataFinal={dataFinal}

Para maiores detalhes cheque a seção Referências.

# Parâmetros iniciais para aquisição do IPCA e Selic.
dataInicial <- "01/01/2015"
dataFinal <- "01/09/2023"
formato <- "json"
cod_ipca <- "10844"
cod_selic <- "4390"
IPCA

Definindo caminho:

ipca_url <- sprintf("https://api.bcb.gov.br/dados/serie/bcdata.sgs.%s/dados?formato=%s&dataInicial=%s&dataFinal=%s", cod_ipca, formato, dataInicial, dataFinal)
cat(ipca_url)
## https://api.bcb.gov.br/dados/serie/bcdata.sgs.10844/dados?formato=json&dataInicial=01/01/2015&dataFinal=01/09/2023

Realizando requisição e transformando conteúdo _*.json_ em DataFrame para ser trabalhado:

ipca_df <- jsonlite::fromJSON(ipca_url)
ipca_df
Selic

Definindo caminho:

selic_url <- sprintf("https://api.bcb.gov.br/dados/serie/bcdata.sgs.%s/dados?formato=%s&dataInicial=%s&dataFinal=%s", cod_selic, formato, dataInicial, dataFinal)
cat(selic_url)
## https://api.bcb.gov.br/dados/serie/bcdata.sgs.4390/dados?formato=json&dataInicial=01/01/2015&dataFinal=01/09/2023

Realizando requisição e transformando conteúdo _*.json_ em DataFrame para ser trabalhado:

selic_df <- jsonlite::fromJSON(selic_url)
selic_df


1. Preparação dos dados

1.1. Apresentação dos dados

O presente trabalho trabalhou com quatro Data Frames, contendo dados sobre índices IFIX, IBOV, IPCA e Selic. Organizado temporalmente em intervalo de meses. Os dados “crús” podem ser visualizados logo abaixo:

Clique acima para selecionar qual deseja visualizar.

IFIX

ifix_df

Checando dados faltantes:

ifix_df[is.na(ifix_df) == TRUE]
## character(0)

IBOV

ibov_df

Checando dados faltantes:

ibov_df[is.na(ibov_df) == TRUE]
## character(0)

IPCA

ipca_df

Checando dados faltantes:

ipca_df[is.na(ipca_df) == TRUE]
## character(0)

Selic

selic_df

Checando dados faltantes:

selic_df[is.na(selic_df) == TRUE]
## character(0)

1.2. Tratamento dos dados

A limpeza e padronização foi realizada da seguinte forma:

  • Defenida uma coluna exclusiva para data e com classe adequada.
  • Todos os dias são rigorosamente o primeiro dia (01), ignorando se foram feriados ou fins de semana.
  • A tabela IFIX e IBOV foi transformada em variação percentual com suas casas decimais (como na tabela IPCA e Selic) e com classe adequada.
  • A tabela IFIX e IBOV optou-se pelo valor de Abertura (open).

Por fim, os dados foram consolidados em uma tabela única como exibido abaixo:

Neste momento foi realizado a limpeza e padronização dos dados.

Clique acima para selecionar qual deseja visualizar.

IFIX

# Index (data) para coluna
ifix_df$timestamp <- row.names(ifix_df)
# Formatando data e padronizando dias para 01 ("normalizando" dias úteis)
ifix_df$timestamp <- as.Date(ifix_df$timestamp, format = "%Y-%m-%d")
ifix_df$timestamp <- lubridate::floor_date(ifix_df$timestamp, unit = "month") + days(0)
# Resetando numeração da coluna (index)
ifix_df <- data.frame(ifix_df, row.names = NULL)
# Transformando valores em variações percentuais
ifix_df <- dplyr::mutate(ifix_df, IFIX = ((ifix_df$open - lag(ifix_df$open, default = dplyr::first(ifix_df$open)))/lag(ifix_df$open, default = dplyr::first(ifix_df$open))) * 100)
# Selecionando colunas de interesse
ifix_df <- subset(ifix_df, select = c(timestamp, IFIX))
# Excluindo primeira linha de 12/2014
ifix_df <- dplyr::slice(ifix_df, -1)
# Arredondando decimais para duas casas
ifix_df$IFIX <- round(ifix_df$IFIX, 2)
# Transformando em Tibble Data Frame
ifix_df <- as_tibble(ifix_df)

A variação foi obtida através da fórmula: \[Variação = \dfrac {Valor Posterior- Valor Anterior}{Valor Anterior} \times 100\] Após padronização, temos:

ifix_df

IBOV

# Index (data) para coluna
ibov_df$timestamp <- row.names(ibov_df)
# Formatando data e padronizando dias para 01 ("normalizando" dias úteis)
ibov_df$timestamp <- as.Date(ibov_df$timestamp, format = "%Y-%m-%d")
ibov_df$timestamp <- lubridate::floor_date(ibov_df$timestamp, unit = "month") + days(0)
# Resetando numeração da coluna (index)
ibov_df <- data.frame(ibov_df, row.names = NULL)
# Transformando valores em variações percentuais
ibov_df <- dplyr::mutate(ibov_df, IBOV = ((ibov_df$open - lag(ibov_df$open, default = dplyr::first(ibov_df$open)))/lag(ibov_df$open, default = dplyr::first(ibov_df$open))) * 100)
# Selecionando colunas de interesse
ibov_df <- subset(ibov_df, select = c(timestamp, IBOV))
# Excluindo primeira linha de 12/2014
ibov_df <- dplyr::slice(ibov_df, -1)
# Arredondando decimais para duas casas
ibov_df$IBOV <- round(ibov_df$IBOV, 2)
# Transformando em Tibble Data Frame
ibov_df <- as_tibble(ibov_df)

A variação foi obtida através da fórmula: \[Variação = \dfrac {Valor Posterior- Valor Anterior}{Valor Anterior} \times 100\] Após padronização, temos:

ibov_df

IPCA

# Renomeando coluna
names(ipca_df) <- c("timestamp", "IPCA")
# Padronizando formatação da datação
ipca_df$timestamp <- as.Date(ipca_df$timestamp, format = "%d/%m/%Y")
# Alterando classe <cha> para <dbl>
ipca_df$IPCA <- as.numeric(ipca_df$IPCA)
# Transformando em Tibble Data Frame
ipca_df <- as_tibble(ipca_df)

Após padronização, temos:

ipca_df

Selic

# Renomeando coluna
names(selic_df) <- c("timestamp", "Selic")
# Padronizando formatação da datação
selic_df$timestamp <- as.Date(selic_df$timestamp, format = "%d/%m/%Y")
# Alterando classe <cha> para <dbl>
selic_df$Selic <- as.numeric(selic_df$Selic)
# Transformando em Tibble Data Frame
selic_df <- as_tibble(selic_df)

Após padronização, temos:

selic_df

Consolidação

combined_df <- ifix_df %>%
  left_join(ibov_df, by = "timestamp") %>%
  left_join(ipca_df, by = "timestamp") %>%
  left_join(selic_df, by = "timestamp")

combined_df
# Checando faltantes devido merge
combined_df[is.na(combined_df) == TRUE]
## [1] NA NA NA
# Dado faltante de Setembro de 2023 por ser mês corrente.
tail(combined_df$IPCA,10)
##  [1]  0.60  1.41  0.25  0.52 -0.06  0.62  0.25  0.08    NA    NA
# Exclusão das duas últimas linhas (setembro/outrubro)
df_sem_ultima_linha <- combined_df[1:(nrow(combined_df) - 2), ]
tail(df_sem_ultima_linha$IPCA,10)
##  [1]  0.13  0.44  0.60  1.41  0.25  0.52 -0.06  0.62  0.25  0.08


2. Análise

2.1 Análise Gráfica

Os dados, agora padronizados, são exibidos em for gráfica logo abaixo. O gráfico das variações exibe apenas as ocilações e poucas informações oferece de forma isolada. Logo em seguida, através de uma soma acumulada das variações, um gráfico representando melhor o intervalo foi elaborado.

Os gráficos são interativos, é possível isolar períodos ao clicar, segurar e arrastar pelos intervalos desejados. Ou deixar mouse em cima do mês de interesse para que seja exibido detalhes em uma etiqueta que surgirá.

Clique acima para selecionar qual deseja visualizar.

Gráfico das Variações

plot_var <- plot_ly(data = combined_df, x = ~timestamp, type = "scatter",
                    y = ~IFIX, mode = "lines", name = "IFIX") %>%
  add_trace(y = ~IBOV, mode = "lines", name = "IBOV") %>%
  add_trace(y = ~IPCA, mode = "lines", name = "IPCA") %>%
  add_trace(y = ~Selic, mode = "lines", name = "Selic") %>%
  layout(title = "Variações do Período",
         font = list(color = "white"),
         xaxis = list(title = "Data", nticks = 9, gridcolor = "#303030"),
         yaxis = list(title = "Variação (valores em porcentagem)", gridcolor = "#303030"),
         hovermode = "x unified",
         paper_bgcolor = "#222222",
         plot_bgcolor = "#222222",
         colorway = c("#ff7f0e","#17becf","#d62728","#33a02c")
         )

plot_var

Gráfico Acumulado

# Soma acumulada das variações
acum_df <- combined_df
acum_df$IFIX <- cumsum(acum_df$IFIX)
acum_df$IBOV <- cumsum(acum_df$IBOV)
acum_df$IPCA <- cumsum(acum_df$IPCA)
acum_df$Selic <- cumsum(acum_df$Selic)
plot_acum <- plot_ly(data = acum_df, x = ~timestamp, type = "scatter",
                      y = ~IFIX, mode = "lines", name = "IFIX") %>%
  add_trace(y = ~IBOV, mode = "lines", name = "IBOV") %>%
  add_trace(y = ~IPCA, mode = "lines", name = "IPCA") %>%
  add_trace(y = ~Selic, mode = "lines", name = "Selic") %>%
  layout(title = "Variação Acumulada do Período",
         font = list(color = "white"),
         xaxis = list(title = "Data", nticks = 9, gridcolor = "#303030"),
         yaxis = list(title = "Rendimento (valores em porcentagem)", gridcolor = "#303030"),
         hovermode = "x unified",
         paper_bgcolor = "#222222",
         plot_bgcolor = "#222222",
         colorway = c("#ff7f0e","#17becf","#d62728","#33a02c")
         )

plot_acum

2.2 Estatística Descritiva

Leia sobre a Análise Gráfica realizada clicando no botão:

No período o IFIX apresenta uma volatilidade considerável (mínima de -15 à máxima de 10 ), talvez tenha sido tão grande devido mudanças de governo (momentos súbitos e dicotômicos de Selic alta/baixa) e principalmente pandemia. O IBOV é conhecidamente um índice volátil por representar ações, no obstante, o afirmado sobre IFIX possivelmente aplica-se aqui também.

A média do IFIX neste período foi uma surpresa, pois é superior a média IBOV. Dessa forma, demonstrando ser preferível no quesito “rentabilidade”, especialmente se julgar a questão da segurança, onde a oscilação do IFIX é inferior ao IBOV. Adicionalmente, esse argumento é suportado pelos dados apresentados nos quartis. Isto é, volatilidade menor, supostamente maior “segurança”. Embora tais afirmativas acerca da análises sejam limitadas, devido intervalo mensal, esta problemática foi melhor abordada no tópico Considerações Finais.

A mínima do IPCA ser negativa implica deflação e, objetivamente, um possível momento de superação de uma crise ou momento de grande incerteza/variabilidade.

Em termos de amostral e representatividade, existem duas posturas diametralmente opostas a se refletir:

    1. É um excelente amostral pois período têm passagens de governo, impeachment, pandemia, selic alta/baixa…
    1. É um péssimo amostral pois foi altamente comprometido por dados “ruidosos”. Mas assim não é a realidade?
summary(df_sem_ultima_linha[,c("IFIX","IBOV","IPCA","Selic")])
##       IFIX               IBOV              IPCA             Selic       
##  Min.   :-15.8500   Min.   :-29.970   Min.   :-0.4700   Min.   :0.1300  
##  1st Qu.: -0.8650   1st Qu.: -3.120   1st Qu.: 0.1950   1st Qu.:0.4700  
##  Median :  1.0300   Median :  0.840   Median : 0.3900   Median :0.7300  
##  Mean   :  0.9073   Mean   :  1.099   Mean   : 0.4062   Mean   :0.7154  
##  3rd Qu.:  2.6150   3rd Qu.:  6.035   3rd Qu.: 0.6200   3rd Qu.:1.0550  
##  Max.   : 10.6300   Max.   : 16.960   Max.   : 1.4100   Max.   :1.2200

Para melhor analisar o comportamento desses índices, a seguir foi realizado uma análise de correlação (Correlação de Pearson).

2.3 Análise de Correlação

Para realizar o cálculo de correlação, primeiramente será considerado período de doze meses. Isto é, “nos ultimos 12 meses a taxa do índice x foi y…”.

Leia sobre a Análise de Correlação realizada clicando no botão:

Definindo data frame com a somatória acumulada do último ano. Obviamente os valores dos primeiros meses apenas consideram eles mesmo, dessa forma os primeiros meses têm valores inferiores ao intervalo de 12 meses. Mas isso não interfere neste cálculo, pois considera apenas a interação entre eles.

# Data frame contendo valores do ultimo ano.
l12df <- combined_df %>%
  mutate(across(c(IFIX, IBOV, IPCA, Selic), 
                ~ cumsum(.) - lag(cumsum(.), n = 12, default = 0)))
l12df

Dessa forma, abaixo a representação gráfica da variação acumulada móvel do período:

plot_last12 <- plot_ly(data = l12df, x = ~timestamp, type = "scatter",
                      y = ~IFIX, mode = "lines", name = "IFIX") %>%
  add_trace(y = ~IBOV, mode = "lines", name = "IBOV") %>%
  add_trace(y = ~IPCA, mode = "lines", name = "IPCA") %>%
  add_trace(y = ~Selic, mode = "lines", name = "Selic") %>%
  layout(title = "Variação Acumulada Móvel com Intervalo de 12 meses",
         font = list(color = "white"),
         xaxis = list(title = "Data", nticks = 9, gridcolor = "#303030"),
         yaxis = list(title = "Variação (valores em porcentagem)", gridcolor = "#303030"),
         hovermode = "x unified",
         paper_bgcolor = "#222222",
         plot_bgcolor = "#222222",
         colorway = c("#ff7f0e","#17becf","#d62728","#33a02c")
         )

plot_last12

O gráfico acima, aparentemente conta uma história, especialmente se focarmos nos índices Selic. Se observamos, à princípio, logo após uma estabilização ou queda da Selic, o IFIX e IBOV valorizam (período de 2017 à 2022). Por outro lado, em um movimento de alta da Selic (período de 2015 à 2016 e novamente de 2022 à 2023) houve desvalorização do IFIX e IBOV.

Embora com o gráfico acima seja possível hipotetizar a afirmativa anterior, qualquer investidor minimamente estudado certamente já concluiu o mesmo. Abaixo foi calculado a grandeza dessa correlação.

# Excluindo duas últimas linhas devido dado faltante do IPCA.
l12df_sem_ultima_linha <- l12df[1:(nrow(l12df) - 2), ]
# Realizando cálculo da correlação
l12cor <- cor(l12df_sem_ultima_linha[, c("IFIX", "IBOV", "IPCA", "Selic")])
l12cor
##            IFIX        IBOV       IPCA       Selic
## IFIX  1.0000000  0.63192296  0.1043657  0.44200095
## IBOV  0.6319230  1.00000000 -0.2823617 -0.02893405
## IPCA  0.1043657 -0.28236169  1.0000000  0.81675913
## Selic 0.4420010 -0.02893405  0.8167591  1.00000000
heatmap_l12 <- plot_ly(
  type = "heatmap",
  colorscale = "Portland",
  z = l12cor,
  x = colnames(l12cor),
  y = rownames(l12cor),
  zmin = -1,  
  zmax = 1,
  reversescale = TRUE
) %>% layout(
    title = "Matriz de Correlação",
    font = list(color = '#FFFFFF'),
    paper_bgcolor = "#222222",
    showlegend = FALSE
  )

# Exibindo anotações no gráfico onde valor diferente de 1.
for (nr in 1:nrow(l12cor)) {
  for (nc in 1:ncol(l12cor)) {
    if (l12cor[nr, nc] != 1) {
      heatmap_l12 <- heatmap_l12 %>%
        add_annotations(
          text = round(l12cor[nr, nc], 6),
          x = colnames(l12cor)[nc],
          y = rownames(l12cor)[nr],
          showarrow = FALSE,
          font = list(size = 14, color = "white"))}}}

heatmap_l12

A relação IFIX x IBOV (0.64) exibe uma moderada correlação e positiva. Sugerindo que tendem a se mover na mesma direção juntos, embora a forma não seja perfeitamente linear.

A relação IPCA x Selic (0.82) exibe uma alta correlação e positiva. O que é esperado já que uma das funçãos da Selic é justamente controlar a inflação.

Tendo em mente o periodo amostral selecionado (de 2015 à 2023) ser possivelmente pequeno e principalmente intervalo (mensal) ser pequeno, pode ter ocasionado nessa aparente “ausência de expressividade” nas correlações calculadas.


3. Previsão

3.1 Estacionareidade IFIX

Para exibir a análise clique no botão:

Checando dados:

# Análise gráfica rápida do data frame
plot.ts(df_sem_ultima_linha)

# Relembrando os 105 valores
df_sem_ultima_linha$IFIX
##   [1]   2.69  -0.27  -1.62   3.68   1.47   3.03   0.70  -0.87  -3.94   2.13
##  [11]   1.58  -3.01  -6.11   2.88   9.16   4.61   3.74   1.60   5.97   1.80
##  [21]   2.77   3.85  -2.59   1.50   3.75   4.87   0.19   0.15   1.03   0.84
##  [31]  -0.38   0.87   6.57   0.23  -0.59   0.60   2.64   1.14   2.00  -0.86
##  [41]  -5.27  -4.02   1.39  -0.71  -0.22   5.04   2.59   2.22   2.47   1.03
##  [51]   1.99   1.03   1.76   2.87   1.28  -0.11   1.04   4.01   3.52  10.63
##  [61]  -3.76  -3.69 -15.85   4.39   2.08   5.59  -2.60   1.79   0.46  -1.01
##  [71]   1.52   2.18   0.32   0.25  -1.38   0.51  -1.54  -2.20   2.51  -2.63
##  [81]  -1.24  -1.47  -3.64   8.78  -0.99  -1.29   1.42   1.19   0.26  -0.88
##  [91]   0.66   5.76   0.49   0.02  -4.15   0.00  -1.60  -0.45  -1.69   3.52
## [101]   5.43   4.71   1.33
# Checando dados estacionários
adf.test(df_sem_ultima_linha$IFIX)
## Warning in adf.test(df_sem_ultima_linha$IFIX): p-value smaller than printed
## p-value
## 
##  Augmented Dickey-Fuller Test
## 
## data:  df_sem_ultima_linha$IFIX
## Dickey-Fuller = -4.736, Lag order = 4, p-value = 0.01
## alternative hypothesis: stationary

Utilizando o ADF Test temos:

  • Hipótese Nula (H0): A série temporal possui raiz unitária (é não estacionária).
  • Hipótese Alternativa (H1): A série temporal não possui raiz unitária (é estacionária).

Sendo o p-valor inverior a 0.05, rejeitamos a hipótese nula (H0). Sugerindo se tratar de uma série é estacionária.

3.2 ARIMA

Para exibir a análise clique no botão:

Checando melhores parâmetros para ARIMA.

auto.arima(df_sem_ultima_linha$IFIX)
## Series: df_sem_ultima_linha$IFIX 
## ARIMA(0,0,3) with non-zero mean 
## 
## Coefficients:
##          ma1     ma2      ma3    mean
##       0.1813  0.0472  -0.3458  0.8961
## s.e.  0.0908  0.0946   0.1015  0.2772
## 
## sigma^2 = 10.38:  log likelihood = -264.83
## AIC=539.65   AICc=540.27   BIC=552.83

Resultando em 0,0,3 (p,d,q ou AR,I,MA).

3.3 Criando modelo

Para exibir a análise clique no botão:

Com os parêmtros anteriores obtidos o modelo a seguir foi obtido:

ifix_mdl <- arima(combined_df$IFIX, order = c(0,0,3))
ifix_mdl
## 
## Call:
## arima(x = combined_df$IFIX, order = c(0, 0, 3))
## 
## Coefficients:
##          ma1     ma2      ma3  intercept
##       0.1820  0.0480  -0.3443     0.9009
## s.e.  0.0899  0.0937   0.1003     0.2727
## 
## sigma^2 estimated as 9.788:  log likelihood = -268.97,  aic = 547.95

3.4. Diagnóstico

Para exibir a análise clique no botão:

3.4.1. Análise de correlação

Checando se os parâmetros são adequados. Isto é, se os resíduos se correlacionam com os parâmetros. Se eles se correlacionarem signica que não está adequado, pois tais resíduos deveriam ser aproveitados na previsão. Com outras palavras, testa o enviesamento dos parâmetros.

res_ifix_mdl <- residuals(ifix_mdl)
res_ifix_mdl
## Time Series:
## Start = 1 
## End = 105 
## Frequency = 1 
##   [1]   1.66547441  -1.35698763  -2.14142330   3.64430149  -0.43570629
##   [6]   1.37393885   0.81280871  -2.12755146  -4.01777475   2.33561207
##  [11]  -0.28582471  -5.35094132  -5.21961199   3.08706585   6.10481560
##  [16]   0.65275810   3.49044081   2.13449718   4.73789792   1.13613881
##  [21]   2.17002242   4.13104095  -3.95577357   1.86831360   4.12127016
##  [26]   1.76712332  -0.58692606   0.69033111   0.64011316  -0.41261261
##  [31]  -0.99874957   0.39116190   5.50375867  -2.03546477  -1.24965296
##  [36]   1.91944034   0.74876706  -0.41955879   1.80053521  -1.81068311
##  [41]  -6.07208751  -3.10862022   0.72283569  -3.68419514  -1.55528121
##  [46]   4.84790304  -0.38740500   0.62155062   3.14390137  -0.60640876
##  [51]   1.26273494   1.01092628   0.40571532   2.28159249   0.29242580
##  [56]  -1.03384677   1.09895773   3.05936613   1.65348199   9.65978212
##  [61]  -5.44522311  -3.49363084 -12.52739687   4.06225113  -0.16241213
##  [66]   0.21013286  -2.13252799   1.21134271  -0.48672410  -2.61468675
##  [71]   1.53558607   0.95742304  -1.72916615   0.14675470  -1.89494990
##  [76]  -0.64836403  -2.18139688  -3.32516111   2.09584665  -4.50403139
##  [81]  -2.56646469  -0.96590460  -5.79283283   8.09628106  -3.41945072
##  [86]  -3.95147701   4.19039407  -1.46159776  -1.93646577   0.08469577
##  [91]  -0.66667577   4.30963171  -1.13426066  -1.11068402  -3.31027712
##  [96]  -0.63554086  -2.60882323  -1.98532103  -2.32314292   2.23896315
## [101]   3.54936359   2.25563565   0.61920833   0.59039642  -0.06133984
acf(res_ifix_mdl)

Tendo em vista que os lag’s (os “picos” no gráfico) se encontram dentro da banda de confiança (tracejado azul horizontal), sugere que os resíduos não se correlacionam com o modelo. Isto é, o modelo realizado captura os padrões nos dados.

3.4.2. Média 0

plot(res_ifix_mdl)

mean(res_ifix_mdl)
## [1] -0.007488662

Nesta etapa foi checado se (em média) os erros de previsão não estão enviesados, acima ou abaixo do valor real. Se os residuos fossem diferentes de 0 sugeriria um enviesamento do modelo. Garantindo assim o comportamento de “ruído branco”.

3.4.3. Distribuição Normal

Checando distribuição normal do resíduo:

gghistogram(res_ifix_mdl)

É desejável o “bell-shape” de uma distribuição normal, sugerindo não haver enviesamento do resíduo.

3.4.4. Conclusão diagnóstico

Os testes anteriores sugere respectivamente que:

  • Os resíduos não são correlacionados com o modelo.
  • Tem média 0 (embora a escala dos valores seja baixa).
  • Os resíduos têm distribuição normal.

Adversamente temos box.test:

Box.test(res_ifix_mdl, lag = 10, type = c("Box-Pierce", "Ljung-Box"), fitdf = 0)
## 
##  Box-Pierce test
## 
## data:  res_ifix_mdl
## X-squared = 1.7771, df = 10, p-value = 0.9978

O p-valor de 99% indica que não há evidência estatisticamente significativa para rejeitar hipótese nula (H0: Não há autocorrelação nos lags considerados). Isto é, exibem independência estatística e modelo captura adequadamente os padrões.

3.5. Previsão

Para exibir a análise clique no botão:

3.5.1. IFIX 01/2015~12/2022

Neste tópico buscou-se predizer o ano de 2023 até setembro, e analisar esta possibilidade. Mas antes usou-se como métrica de comparação a predição que foi realizada a seguir no tópico 3.5.2 que tentará predizer os próximos dois anos a partir do intervalo entre 01/2015 e 09/2023

forecast_ifix <- forecast(ifix_mdl, h = 24)
forecast_ifix
##     Point Forecast     Lo 80    Hi 80     Lo 95    Hi 95
## 106      0.7048021 -3.304586 4.714190 -5.427028 6.836632
## 107      0.6946248 -3.380657 4.769907 -5.537981 6.927231
## 108      0.9219869 -3.157831 5.001805 -5.317557 7.161530
## 109      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 110      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 111      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 112      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 113      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 114      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 115      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 116      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 117      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 118      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 119      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 120      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 121      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 122      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 123      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 124      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 125      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 126      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 127      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 128      0.9008650 -3.406218 5.207948 -5.686250 7.487980
## 129      0.9008650 -3.406218 5.207948 -5.686250 7.487980

Ao prever 24 próximos meses, temos as seguintes colunas:

  • Previsão Point Forecast.
  • Limites 80% Lo80 mínimo e Hi 80 máximo.
  • Limites 95% Lo 95 mínimo e Hi 95 máximo.
plot(forecast_ifix)

Neste momento abordaremos a contrastação com os dados já presentes e concretos do próprio ano de 2023. Isto é possível ser feito ao retirá-lo do amostral ou Out-of-Sample.

O raciocínio é simples: Se estivéssemos em dezembro de 2022, como seria o IFIX de 2023 utilizando esse modelo?

ifix15_22 <- arima(combined_df$IFIX[1:96], order = c(0,0,3))
forecast15_22 <- forecast(ifix15_22, h = 9)
forecast15_22
##     Point Forecast     Lo 80    Hi 80     Lo 95    Hi 95
##  97      0.9986895 -3.112424 5.109803 -5.288717 7.286096
##  98      1.9862036 -2.179274 6.151681 -4.384345 8.356752
##  99      1.1037420 -3.064463 5.271947 -5.270978 7.478462
## 100      0.8790011 -3.514623 5.272625 -5.840467 7.598469
## 101      0.8790011 -3.514623 5.272625 -5.840467 7.598469
## 102      0.8790011 -3.514623 5.272625 -5.840467 7.598469
## 103      0.8790011 -3.514623 5.272625 -5.840467 7.598469
## 104      0.8790011 -3.514623 5.272625 -5.840467 7.598469
## 105      0.8790011 -3.514623 5.272625 -5.840467 7.598469

Avaliando precisão:

accuracy(ifix15_22)
##                        ME     RMSE      MAE MPE MAPE      MASE        ACF1
## Training set -0.007273949 3.207919 2.397492 Inf  Inf 0.7728859 -0.01321303

O MAPE (Erro Percentual Absoluto Médio) sugere que, em média, as previsões têm um erro percentual absoluto médio de aproximadamente 198.12%. Já o modelo até 09/2023.

accuracy(ifix_mdl)
##                        ME     RMSE      MAE MPE MAPE      MASE       ACF1
## Training set -0.007488662 3.128542 2.353064 Inf  Inf 0.7868008 -0.0069888

A piora do modelo de 2022 pode ter acontecido devido ano de eleição com grandes oscilações não-recorrentes.

Padronizando dados do previsto 2015~2022:

# Extraindo valores do forecast:
forecastibble <- tibble(
  Point_Forecast = forecast15_22$mean,
  Lo_80 = forecast15_22$lower[, "80%"],
  Hi_80 = forecast15_22$upper[, "80%"],
  Lo_95 = forecast15_22$lower[, "95%"],
  Hi_95 = forecast15_22$upper[, "95%"])
# Criando linhas e adequando 
b_row <- tibble(
  Point_Forecast = rep(NA, 96),
  Lo_80 = rep(NA, 96),
  Hi_80 = rep(NA, 96),
  Lo_95 = rep(NA, 96)
)
forecastibble <- bind_rows(b_row, forecastibble)
tail(forecastibble,10)

Padronizando informações e consolidando para permitir visualização:

# Recriando data frame com datas e o ifix
ifix_pred <- subset(combined_df, select = c(timestamp, IFIX))
# Unindo o data frame com predições do ano de 2023
ifix_pred <- merge(ifix_pred, forecastibble, by = 0)
# Removendo index
ifix_pred$Row.names <- NULL
# Reorganizando em ordem crescente
ifix_pred <- ifix_pred %>%
  arrange(as.Date(timestamp))
# Separando em dois dataframes para poder replicar valores do ifix até 12/2022
ifix_pred_slice_top <- slice(ifix_pred, 1:96)
ifix_pred_slice_bottom <- slice(ifix_pred, 97:105)

# Replicando valores de IFIX para demais colunas
ifix_pred_slice_top <- ifix_pred_slice_top %>%
  mutate(
    Point_Forecast = ifix_pred_slice_top$IFIX,
    Lo_80 = ifix_pred_slice_top$IFIX,
    Hi_80 = ifix_pred_slice_top$IFIX,
    Lo_95 = ifix_pred_slice_top$IFIX,
    Hi_95 = ifix_pred_slice_top$IFIX
  )

# Unindo metades
ifix_pred <- rbind(ifix_pred_slice_top, ifix_pred_slice_bottom)

# Soma acumulada das variações
ifix_pred$IFIX <- cumsum(ifix_pred$IFIX)
ifix_pred$Prd <- round(cumsum(ifix_pred$Point_Forecast),2)
ifix_pred$L80 <- round(cumsum(ifix_pred$Lo_80),2)
ifix_pred$H80 <- round(cumsum(ifix_pred$Hi_80),2)
ifix_pred$L95 <- round(cumsum(ifix_pred$Lo_95),2)
ifix_pred$H95 <- round(cumsum(ifix_pred$Hi_95),2)
ifix_pred <- subset(ifix_pred, select = c(timestamp, IFIX, Prd, L80, H80, L95, H95))

ifix_pred

Analisando previsão de forma gráfica:

plt_pred_ifix <- plot_ly(data = ifix_pred, x = ~timestamp, type = "scatter",
                      y = ~IFIX, mode = "lines", name = "IFIX") %>%
  add_trace(y = ~Prd, mode = "lines", name = "Predito") %>%
  add_trace(y = ~L80, mode = "lines", name = "Menor 80%") %>%
  add_trace(y = ~H80, mode = "lines", name = "Maior 80%") %>%
  add_trace(y = ~L95, mode = "lines", name = "Menor 95%") %>%
  add_trace(y = ~H95, mode = "lines", name = "Maior 95%") %>%
  add_ribbons(ymin = ~L80, ymax = ~H80, color = I("rgba(51, 160, 44, 0.3)"),
              name = "Intervalo 80%", showlegend = FALSE) %>%
  add_ribbons(ymin = ~L95, ymax = ~H95, color = I("rgba(214, 39, 40, 0.3)"),
              name = "Intervalo 95%", showlegend = FALSE) %>%
  layout(title = "Predição IFIX 2023",
         font = list(color = "white"),
         xaxis = list(title = "Data", nticks = 9, gridcolor = "#303030"),
         yaxis = list(title = "Rendimento (valores em porcentagem)", gridcolor = "#303030"),
         hovermode = "x unified",
         paper_bgcolor = "#222222",
         plot_bgcolor = "#222222",
         colorway = c("#ff7f0e","#17becf","#33a02c",
                      "#33a02c","#d62728","#d62728","#d62728")
         )

plt_pred_ifix

Analisando predito de forma gráfica exclusivamente no período proposto:

# Filtrando para iniciar a partir de dez/2022
ifix_pred_filter <- ifix_pred %>%
  filter(row_number() >= 96)

# Criando o gráfico
f_plt_pred_ifix <- plot_ly(data = ifix_pred_filter, x = ~timestamp, type = "scatter",
                      y = ~IFIX, mode = "lines", name = "IFIX") %>%
  add_trace(y = ~Prd, mode = "lines", name = "Predito") %>%
  add_trace(y = ~L80, mode = "lines", name = "Menor 80%") %>%
  add_trace(y = ~H80, mode = "lines", name = "Maior 80%") %>%
  add_trace(y = ~L95, mode = "lines", name = "Menor 95%") %>%
  add_trace(y = ~H95, mode = "lines", name = "Maior 95%") %>%
  add_ribbons(ymin = ~L80, ymax = ~H80, color = I("rgba(51, 160, 44, 0.3)"),
              name = "Intervalo 80%", showlegend = FALSE) %>%
  add_ribbons(ymin = ~L95, ymax = ~H95, color = I("rgba(214, 39, 40, 0.3)"),
              name = "Intervalo 95%", showlegend = FALSE) %>%
  layout(title = "Predição IFIX 2023",
         font = list(color = "white"),
         xaxis = list(title = "Data", nticks = 1, gridcolor = "#303030"),
         yaxis = list(title = "Rendimento (valores em porcentagem)", gridcolor = "#303030"),
         hovermode = "x unified",
         paper_bgcolor = "#222222",
         plot_bgcolor = "#222222",
         colorway = c("#ff7f0e","#17becf","#33a02c",
                      "#33a02c","#d62728","#d62728","#d62728")
         )

f_plt_pred_ifix

Como o modelo aqui desenvolvido, no intervalo entre 01/2015 e 12/2022, predisse o ano de 2023 até o mês de setembro?

A variação é grande pois quanto mais “no futuro”, maior a chance de erro, em outras palavras, “acumuladamente” o erro se dá. Outro grande fator, que se hipotetiza, é que as eleições de 2022 podem ter contribuído para uma maior oscilação não-recorrente do período observado.

3.5.2. IFIX 01/2015~09/2023

No intervalo entre 01/2015 e 09/2023, como o modelo aqui desenvolvido predisse o intervalo de 10/2023 até 09/2025 ?

# Repetindo código para gerar predições
forecast_ifix <- forecast(ifix_mdl, h = 24)

# Extraindo valores do forecast:
forecast_ifix <- tibble(
  Point_Forecast = forecast_ifix$mean,
  Lo_80 = forecast_ifix$lower[, "80%"],
  Hi_80 = forecast_ifix$upper[, "80%"],
  Lo_95 = forecast_ifix$lower[, "95%"],
  Hi_95 = forecast_ifix$upper[, "95%"])

forecast_ifix <- forecast_ifix %>%
  mutate(timestamp = seq.Date(from = as.Date("2023-10-01"),
                              to = as.Date("2025-09-01"),
                              by = "month"))

# Recriando data frame com datas e o ifix
forecast_ifix_pred <- subset(combined_df, select = c(timestamp, IFIX))

# Replicando valores de IFIX para demais colunas
forecast_ifix_pred <- forecast_ifix_pred %>%
  mutate(
    Lo_80 = forecast_ifix_pred$IFIX,
    Hi_80 = forecast_ifix_pred$IFIX,
    Lo_95 = forecast_ifix_pred$IFIX,
    Hi_95 = forecast_ifix_pred$IFIX
  )

# Renomeando coluna para compatibilidade
forecast_ifix <- forecast_ifix %>%
  rename(IFIX = Point_Forecast)

# Consolidando dados
forecast_ifix_pred <- rbind(forecast_ifix_pred, forecast_ifix)

# Soma acumulada das variações
forecast_ifix_pred$IFIX <- round(cumsum(forecast_ifix_pred$IFIX),2)
forecast_ifix_pred$L80 <- round(cumsum(forecast_ifix_pred$Lo_80),2)
forecast_ifix_pred$H80 <- round(cumsum(forecast_ifix_pred$Hi_80),2)
forecast_ifix_pred$L95 <- round(cumsum(forecast_ifix_pred$Lo_95),2)
forecast_ifix_pred$H95 <- round(cumsum(forecast_ifix_pred$Hi_95),2)
forecast_ifix_pred <- subset(forecast_ifix_pred, select = c(timestamp, IFIX, L80, H80, L95, H95))

forecast_ifix_pred

Analisando previsão de forma gráfica:

plt_pred_25 <- plot_ly(data = forecast_ifix_pred, x = ~timestamp, type = "scatter",
                      y = ~IFIX, mode = "lines", name = "IFIX") %>%
  add_trace(y = ~L80, mode = "lines", name = "Menor 80%") %>%
  add_trace(y = ~H80, mode = "lines", name = "Maior 80%") %>%
  add_trace(y = ~L95, mode = "lines", name = "Menor 95%") %>%
  add_trace(y = ~H95, mode = "lines", name = "Maior 95%") %>%
  add_ribbons(ymin = ~L80, ymax = ~H80, color = I("rgba(51, 160, 44, 0.3)"),
              name = "Intervalo 80%", showlegend = FALSE) %>%
  add_ribbons(ymin = ~L95, ymax = ~H95, color = I("rgba(214, 39, 40, 0.3)"),
              name = "Intervalo 95%", showlegend = FALSE) %>%
  layout(title = "Predição IFIX 2025",
         font = list(color = "white"),
         xaxis = list(title = "Data", nticks = 11, gridcolor = "#303030"),
         yaxis = list(title = "Rendimento (valores em porcentagem)", gridcolor = "#303030"),
         hovermode = "x unified",
         paper_bgcolor = "#222222",
         plot_bgcolor = "#222222",
         colorway = c("#ff7f0e","#17becf","#33a02c",
                      "#33a02c","#d62728","#d62728","#d62728")
         )

plt_pred_25

Analisando predito de forma gráfica exclusivamente no período proposto:

# Filtrando para iniciar a partir de dez/2022
ifix_pred_filter_25 <- forecast_ifix_pred %>%
  filter(row_number() >= 105)

# Criando o gráfico
f_plt_pred_ifix_25 <- plot_ly(data = ifix_pred_filter_25, x = ~timestamp, type = "scatter", y = ~IFIX, mode = "lines", name = "IFIX") %>%
  add_trace(y = ~L80, mode = "lines", name = "Menor 80%") %>%
  add_trace(y = ~H80, mode = "lines", name = "Maior 80%") %>%
  add_trace(y = ~L95, mode = "lines", name = "Menor 95%") %>%
  add_trace(y = ~H95, mode = "lines", name = "Maior 95%") %>%
  add_ribbons(ymin = ~L80, ymax = ~H80, color = I("rgba(51, 160, 44, 0.3)"),
              name = "Intervalo 80%", showlegend = FALSE) %>%
  add_ribbons(ymin = ~L95, ymax = ~H95, color = I("rgba(214, 39, 40, 0.3)"),
              name = "Intervalo 95%", showlegend = FALSE) %>%
  layout(title = "Predição IFIX 2025",
         font = list(color = "white"),
         xaxis = list(title = "Data", nticks = 4, gridcolor = "#303030"),
         yaxis = list(title = "Rendimento (valores em porcentagem)", gridcolor = "#303030"),
         hovermode = "x unified",
         paper_bgcolor = "#222222",
         plot_bgcolor = "#222222",
         colorway = c("#ff7f0e","#17becf","#33a02c",
                      "#33a02c","#d62728","#d62728","#d62728"))

f_plt_pred_ifix_25


Conclusão

Assume-se que um bom investimento é realizado no lugar, momento e valor adequado. Neste tópico se propôs refletir sobre a interação dessas três variáveis, problemas e possíveis soluções implícitas.

Lugar

O presente estudo teve como objetivo analisar o índice IFIX, suas correlações e possibilidade de predizer tendência baseado em dados desde janeiro de 2015 à setembro de 2023. Analisou correlações com outros índices do mercado, como IBOV, Selic e IPCA. Buscando em um primeiro momento correlações e posteriormente projetar tendência.

Momento

Uma grande parte do que se entende como “lucro” parte da premissa do momento. No caso de investimentos, pode ser melhor expressada pela “antecipação” deste momento. O presente trabalho não analisou a quase infinita míriade de possibilidades que impactam esse dito “momento”. Como por exemplo, reuniões do COPOM (Comitê de Política Monetária) que dita a previsão da taxa selic.

Sucintamente, uma diminuicão no gráfico da Selic (exposto no trabalho), meses antes já impactou nos índices de renda variável IFIX e IBOV. Em outras palavras, quedas abruptas “hoje” na renda variável talvez possam ser explicadas devido taxas elevadas previstas pelo COPOM nos “próximos meses”.

Ademais, tendo em vista a janela amostral (de sete anos) e seu intervalo (em meses), conclui-se que possui limitações em detrimento dessas variáveis. Adicionalmente há de se considerar contexto dos ultimos anos conturbados de pandemia, impeachment, trocas de governo e amplitude da taxa Selic. Uma janela maior e intervalos menores potencialmente abarcaria de forma mais adequada essa intrínseca conexão.

Valor

A íntrínseca conexão é possivel ser vista nesta variável. Como no final das eleições de 2022 ao tentar prever valores de 2023 (tópico 3.5.1). Com outras palavras, dinheiro só possui valor no tempo.

Por fim, cabe afirmar que o presente trabalho cumpriu com o objetivo de analisar sob caráter experimental e expeculativo. E, de certa forma, pode ser visto como um rascunho do que “pode ser feito”. Pois este, se trata apenas um mero exercício didático com fim de explorar e exibir repertório acerca dos conteúdos aqui abordados.